

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>


<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<base target="_top">
<style type="text/css">
  

/* default css */

table {
  font-size: 1em;
  line-height: inherit;
  border-collapse: collapse;
}


tr {
  
  text-align: left;
  
}


div, address, ol, ul, li, option, select {
  margin-top: 0px;
  margin-bottom: 0px;
}

p {
  margin: 0px;
}


pre {
  font-family: Courier New;
  white-space: pre-wrap;
  margin:0;
}

body {
  margin: 6px;
  padding: 0px;
  font-family: Verdana, sans-serif;
  font-size: 10pt;
  background-color: #ffffff;
  color: #000;
}


img {
  -moz-force-broken-image-icon: 1;
}

@media screen {
  html.pageview {
    background-color: #f3f3f3 !important;
    overflow-x: hidden;
    overflow-y: scroll;
  }

  

  body {
    min-height: 1100px;
    
    counter-reset: __goog_page__;
  }
  
  * html body {
    height: 1100px;
  }
  /* Prevent repaint errors when scrolling in Safari. This "Star-7" css hack
     targets Safari 3.1, but not WebKit nightlies and presumably Safari 4.
     That's OK because this bug is fixed in WebKit nightlies/Safari 4 :-). */
  html*#wys_frame::before {
    content: '\A0';
    position: fixed;
    overflow: hidden;
    width: 0;
    height: 0;
    top: 0;
    left: 0;
  }
  
  .pageview body {
    border-top: 1px solid #ccc;
    border-left: 1px solid #ccc;
    border-right: 2px solid #bbb;
    border-bottom: 2px solid #bbb;
    width: 648px !important;
    margin: 15px auto 25px;
    padding: 40px 50px;
  }
  /* IE6 */
  * html {
    overflow-y: scroll;
  }
  * html.pageview body {
    overflow-x: auto;
  }
  

  
    
    .writely-callout-data {
      display: none;
    }
    

    .writely-footnote-marker {
      background-image: url('MISSING');
      background-color: transparent;
      background-repeat: no-repeat;
      width: 7px;
      overflow: hidden;
      height: 16px;
      vertical-align: top;

      
      -moz-user-select: none;
    }
    .editor .writely-footnote-marker {
      cursor: move;
    }
    .writely-footnote-marker-highlight {
      background-position: -15px 0;
      -moz-user-select: text;
    }
    .writely-footnote-hide-selection ::-moz-selection, .writely-footnote-hide-selection::-moz-selection {
      background: transparent;
    }
    .writely-footnote-hide-selection ::selection, .writely-footnote-hide-selection::selection {
      background: transparent;
    }
    .writely-footnote-hide-selection {
      cursor: move;
    }

    /* Comments */
    .writely-comment-yellow {
      background-color: #ffffd7;
    }
    .writely-comment-orange {
      background-color: #ffe3c0;
    }
    .writely-comment-pink {
      background-color: #ffd7ff;
    }
    .writely-comment-green {
      background-color: #d7ffd7;
    }
    .writely-comment-blue {
      background-color: #d7ffff;
    }
    .writely-comment-purple {
      background-color: #eed7ff;
    }

  


  
  .br_fix span+br:not(:-moz-last-node) {
    
    position:relative;
    
    left: -1ex
    
  }

  
  #cb-p-tgt {
    font-size: 8pt;
    padding: .4em;
    background-color: #ddd;
    color: #333;
  }
  #cb-p-tgt-can {
    text-decoration: underline;
    color: #36c;
    font-weight: bold;
    margin-left: 2em;
  }
  #cb-p-tgt .spin {
    width: 16px;
    height: 16px;
    background: url(//ssl.gstatic.com/docs/clipboard/spin_16o.gif) no-repeat;
  }
}

h6 { font-size: 8pt }
h5 { font-size: 8pt }
h4 { font-size: 10pt }
h3 { font-size: 12pt }
h2 { font-size: 14pt }
h1 { font-size: 18pt }

blockquote {padding: 10px; border: 1px #DDD dashed }

.webkit-indent-blockquote { border: none; }

a img {border: 0}

.pb {
  border-width: 0;
  page-break-after: always;
  /* We don't want this to be resizeable, so enforce a width and height
     using !important */
  height: 1px !important;
  width: 100% !important;
}

.editor .pb {
  border-top: 1px dashed #C0C0C0;
  border-bottom: 1px dashed #C0C0C0;
}

div.google_header, div.google_footer {
  position: relative;
  margin-top: 1em;
  margin-bottom: 1em;
}


/* Table of contents */
.editor div.writely-toc {
  background-color: #f3f3f3;
  border: 1px solid #ccc;
}
.writely-toc > ol {
  padding-left: 3em;
  font-weight: bold;
}
ol.writely-toc-subheading {
  padding-left: 1em;
  font-weight: normal;
}
/* IE6 only */
* html writely-toc ol {
  list-style-position: inside;
}
.writely-toc-none {
  list-style-type: none;
}
.writely-toc-decimal {
  list-style-type: decimal;
}
.writely-toc-upper-alpha {
  list-style-type: upper-alpha;
}
.writely-toc-lower-alpha {
  list-style-type: lower-alpha;
}
.writely-toc-upper-roman {
  list-style-type: upper-roman;
}
.writely-toc-lower-roman {
  list-style-type: lower-roman;
}
.writely-toc-disc {
  list-style-type: disc;
}

/* Ordered lists converted to numbered lists can preserve ordered types, and
   vice versa. This is confusing, so disallow it */
ul[type="i"], ul[type="I"], ul[type="1"], ul[type="a"], ul[type="A"] {
  list-style-type: disc;
}

ol[type="disc"], ol[type="circle"], ol[type="square"] {
  list-style-type: decimal;
}

/* end default css */


  /* default print css */
  @media print {
    body {
      padding: 0;
      margin: 0;
    }

    div.google_header, div.google_footer {
      display: block;
      min-height: 0;
      border: none;
    }

    div.google_header {
      flow: static(header);
    }

    /* used to insert page numbers */
    div.google_header::before, div.google_footer::before {
      position: absolute;
      top: 0;
    }

    div.google_footer {
      flow: static(footer);
    }

    /* always consider this element at the start of the doc */
    div#google_footer {
      flow: static(footer, start);
    }

    span.google_pagenumber {
      content: counter(page);
    }

    span.google_pagecount {
      content: counter(pages);
    }

    .endnotes {
      page: endnote;
    }

    /* MLA specifies that endnotes title should be 1" margin from the top of the page. */
    @page endnote {
      margin-top: 1in;
    }

    callout.google_footnote {
      
      display: prince-footnote;
      footnote-style-position: inside;
      /* These styles keep the footnote from taking on the style of the text
         surrounding the footnote marker. They can be overridden in the
         document CSS. */
      color: #000;
      font-family: Verdana;
      font-size: 10.0pt;
      font-weight: normal;
    }

    /* Table of contents */
    #WritelyTableOfContents a::after {
      content: leader('.') target-counter(attr(href), page);
    }

    #WritelyTableOfContents a {
      text-decoration: none;
      color: black;
    }

    /* Comments */
    .writely-comment-yellow {
      background-color: #ffffd7;
    }
    .writely-comment-orange {
      background-color: #ffe3c0;
    }
    .writely-comment-pink {
      background-color: #ffd7ff;
    }
    .writely-comment-green {
      background-color: #d7ffd7;
    }
    .writely-comment-blue {
      background-color: #d7ffff;
    }
    .writely-comment-purple {
      background-color: #eed7ff;
    }
  }

  @page {
    @top {
      content: flow(header);
    }
    @bottom {
      content: flow(footer);
    }
    @footnotes {
      border-top: solid black thin;
      padding-top: 8pt;
    }
  }
  /* end default print css */


/* custom css */


/* end custom css */

/* ui edited css */

body {
  font-family: Verdana;
  
  font-size: 10.0pt;
  line-height: normal;
  background-color: #ffffff;
}
/* end ui edited css */


/* editor CSS */
.editor a:visited {color: #551A8B}
.editor table.zeroBorder {border: 1px dotted gray}
.editor table.zeroBorder td {border: 1px dotted gray}
.editor table.zeroBorder th {border: 1px dotted gray}


.editor div.google_header, .editor div.google_footer {
  border: 2px #DDDDDD dashed;
  position: static;
  width: 100%;
  min-height: 2em;
}

.editor .misspell {background-color: yellow}

.editor .writely-comment {
  font-size: 9pt;
  line-height: 1.4;
  padding: 1px;
  border: 1px dashed #C0C0C0
}


/* end editor CSS */

</style>

  
  <title> W2 Komunikacja</title>

</head>

<body 
    
    >
    
    
    
<div id=ocnl style=TEXT-ALIGN:left>
  <font size=5><b style=COLOR:#3d85c6>Komunikacja</b></font><br>
  <hr size=2><br>
</div>
Komunikacja pomiędzy procesami jest centralnym elementem systemu rozproszonego. Niniejszy wykład omawia różne modele komunikacji, zgodnie z ich rosnącym poziomem abstrakcji. Na początku przedstawiono podstawowe koncepcje związane z niskopoziomową wymianą wiadomości w sieciach komputerowych, a następnie mechanizmy wyższego poziomu, dostarczające wygodniejszych niż wysyłanie i odbieranie wiadomości mechanizmów komunikacji takich jak: zdalne wywoływanie procedur (RPC), zdalne wywoływanie metod (RMI), systemy transferu wiadomości oraz komunikację strumieniową.<br>
<br>
<br>
<font size=3><b><font color=#3d85c6>Wymiana wiadomości sieciowych</font></b></font><br>
<hr size=2><br>
<div id=m5vm style=TEXT-ALIGN:left>
  <img src="images/dcjpvv6n_2247d2dhbjn7_b.png" style=HEIGHT:340px;WIDTH:500px><br>
  <br>
  Ze względu na brak pamięci współdzielonej, wszelka komunikacja w systemach rozproszonych odbywa się za pomocą wymiany niskopoziomowych wiadomości sieciowych. Należy przy tym uzgodnić wiele szczegółów. Rozważmy następujący przykład. Gdy proces A chce komunikować się z procesem B, buduje w wiadomość swojej przestrzeni adresowej. Następnie wykonuje wywołanie systemu operacyjnego, które powoduje, że system operacyjny przesyła tę wiadomość do procesu B. Jakie napięcie przyjąć dla oznaczenia bitu 0, a jakie dla bitu 1? Jak odbiorca rozpozna ostatni bit wiadomości? Jak może stwierdzić, że wiadomość została uszkodzona, i co może wówczas zrobić? Ile bitów zajmują dane różnego typu: liczby całkowite, rzeczywiste, znaki itd.? Jak widać, uzgodnienia muszą istnieć na różnych poziomach, począwszy od detali niskopoziomowej transmisji danych, a skończywszy na wysokopoziomowych szczegółach reprezentacji danych.<br>
  <br>
  <br>
  <font size=3><b><font color=#3d85c6>Model warstwowy ISO/OSI</font></b></font><br>
  <hr size=2><br>
  <div id=vgr. style=TEXT-ALIGN:left>
    <img src="images/dcjpvv6n_2248c45c3jhs_b.png" style=HEIGHT:341px;WIDTH:500px>
  </div>
  <br>
  Aby ułatwić ustalanie szczegółów na różnych poziomach abstrakcji, organizacja ISO opublikowała w 1983 roku model odniesienia, który definiuje różne poziomy w postaci warstw, nadaje im standardowe nazwy oraz określa, jaka jest rola każdej warstwy. Model nosi angielską nazwę <i>Open</i> <i>Systems</i> <i>Interconnection</i> , w skrócie <b>OSI</b> i bywa nazywany modelem warstwowym lub modelem OSI.
  <p>
    Protokoły wypracowane w ramach modelu OSI nigdy nie były powszechnie używane, ale sam model okazał się bardzo pomocny do zrozumienia modularnej budowy sieci komputerowych oraz użyteczny w dydaktyce.<br>
  </p>
  <p>
    <br>
  </p>
  <p>
    Pojedyncza warstwa odpowiada za realizację odrębnego zbioru funkcji. Każda warstwa (oprócz najwyższej) dostarcza warstwie będącej bezpośrednio wyżej interfejsu do swoich usług. Komunikacja w sieci zgodnej z modelem warstwowym odbywa się tylko między odpowiadającymi sobie warstwami po obydwu stronach. Warstwa numer N po stronie nadawczej przesyła więc wiadomość tylko do warstwy numer N po stronie odbiorczej. Zestaw mechanizmów definiujących daną warstwę nazywa się <b>protokołem</b> . Jak widać na rysunku, protokoły działają tylko w jednej warstwie.<br>
  </p>
  <p>
    <br>
  </p>
  <p>
    Wyróżnia się dwa typy protokołów. W <b>protokołach</b> <b>połączeniowych</b> (ang. <i>connection-oriented</i> ) przed wymianą danych następuje faza jawnego nawiązania połączenia, a po wymianie danych – faza jawnego zakończenia połączenia. Przykładem komunikacji połączeniowej jest tradycyjna telefonia. W protokołach <b>bezpołączeniowych</b> (ang. <i>connectionless</i> ) strony nie nawiązują połączenia, lecz nadawca wysyła pierwszą wiadomość, gdy tylko jest ona gotowa. Przykładem komunikacji bezpołączeniowej w życiu codziennym jest wysłanie listu pocztą.<br>
  </p>
  <p>
    <br>
  </p>
  <p>
    Jak widać na rysunku, model OSI wyróżnia siedem warstw. Choć w sieci Internet używa się modelu obejmującego cztery warstwy, w dalszej części skupimy się na modelu OSI, gdyż jest bardziej ogólny. Pokrótce omówimy funkcje wszystkich warstw, miejscami odnosząc się do modelu sieci Internet.
  </p>
  <br>
  <br>
  <font size=3><b><font color=#3d85c6>Model warstwowy - kapsułkowanie</font></b></font><br>
  <hr size=2><br>
  <div id=tf7b style=TEXT-ALIGN:left>
    <img src="images/dcjpvv6n_2249czb78vgt_b.png" style=HEIGHT:339px;WIDTH:500px>
  </div>
  <br>
  Komunikację pomiędzy warstwami umożliwia proces zwany <b>kapsułkowaniem</b> (ang. <i>encapsulation</i> ). Kapsułkowanie polega na umieszczeniu wiadomości warstwy wyższej wewnątrz wiadomości warstwy niższej. Zanim wiadomość po stronie nadawczej zostanie wysłana, przekazywana jest przez aplikację „wdół” stosu warstw; każda kolejna warstwa po otrzymaniu tej wiadomości od warstwy wyższej, dodaje do niej własny nagłówek i (rzadziej) stopkę. U odbiorcy natomiast zachodzi proces odwrotny. Wiadomość przekazywana jest „w górę” stosu warstw i każda kolejna warstwa interpretuje, a następnie usuwa nagłówek dodany poprzednio przez tę samą warstwę u nadawcy. Tak okrojona wiadomość przekazywana jest następnie warstwie wyższej. Aplikacja u odbiorcy otrzymuje zatem oryginalne dane, wysłane wcześniej przez aplikację po stronie nadawczej.<br>
  <br>
  <p>
    Każda wiadomość jest złożona z dwóch części. Pierwszą z nich stanowi <b>nagłówek</b> , czyli informacje sterujące, które dana warstwa dodaje w celu komunikowania się z tą samą warstwą po drugiej stronie. Druga część to <b>dane</b> , czyli wszystko to, co dana warstwa otrzymała do wysłania od warstwy wyższej (najczęściej dane te zawierają już kilka nagłówków warstw wyższych).<br>
  </p>
  <p>
    <br>
  </p>
  <p>
    Na rysunku ukazano typową wiadomość utworzoną przez oprogramowanie realizujące model warstwowy OSI, i znajdującą się w warstwie fizycznej, czyli przygotowaną do fizycznego wysłania. Oryginalna wiadomość została obudowana nagłówkami kolejnych warstw, zgodnie z mechanizmem opisanym powyżej. Widać ponadto, że stopkę na końcu wiadomości dołącza tylko warstwa łącza danych.<br>
  </p>
  <p>
    <br>
  </p>
  <p>
    Oczywiście wszystkie informacje sterujące w postaci nagłówków i stopek sprawiają, że w sieci zostanie przesłanych więcej bitów, niż zajmuje oryginalna wiadomość.
  </p>
  <br>
  <br>
  <font size=3><b><font color=#3d85c6>Warstwa fizyczna</font></b></font><br>
  <hr size=2><br>
  <div id=xcfp style=TEXT-ALIGN:left>
    <img src="images/dcjpvv6n_2250cj9vx78f_b.png" style=HEIGHT:342px;WIDTH:500px>
  </div>
  <br>
  Warstwa fizyczna definiuje mechanizmy odpowiedzialne za fizyczną transmisję bitów przez medium komunikacyjne. Specyfikuje również parametry mechaniczne i elektryczne transmisji, które dla warstwy wyższej stanowią interfejs dostępu do warstwy fizycznej.<br>
  <br>
  <br>
  <font size=3><b><font color=#3d85c6>Warstwy 2 do 4<br>
  </font></b></font><hr size=2><font size=3><b><br>
  </b></font>
</div>
<div id=pmhk style=TEXT-ALIGN:left>
  <img src="images/dcjpvv6n_2251d84x9pfx_b.png" style=HEIGHT:341px;WIDTH:500px><br>
  <br>
  Zadaniem warstw: łącza danych, sieciowej oraz transportowej, jest umożliwienie budowania złożonych sieci urządzeń oraz łączenie procesów w takich sieciach. Ilustruje to rysunek na slajdzie. U dołu rysunku widnieje warstwa 2, łącza danych, której zadaniem jest łączenie <i>bezpośrednio</i> <i>sąsiadujących</i> ze sobą urządzeń w niewielkie sieci, zwane sieciami lokalnymi LAN (ang. Local Area Networks). Znajdująca się powyżej warstwa 3, sieciowa, korzysta z funkcjonalności dostarczanej przez warstwę 2, by <i>łączyć</i> <i>lokalne</i> <i>sieci</i> <i>w</i> <i>większą</i> <i>strukturę</i> <i>sieciową</i> , w sieć sieci (najbardziej znanym przykładem takiej sieci jest Internet). W warstwach 2 oraz 3 łączenie dotyczy jednak wyłącznie <i>urządzeń</i> . Dopiero warstwa 4, transportowa, wykorzystuje funkcjonalność warstwy sieciowej, aby umożliwić łączenie <i>procesów</i> pracujących na odległych od siebie komputerach. Można zatem w uproszczeniu powiedzieć, że warstwy 2 i 3 łączą komputery, a warstwa 4 – procesy.<br>
  <br>
  <p>
    W każdej z warstw wykorzystuje się konkretne protokoły. Przykładowo, w sieci Internet w warstwie łącza danych do najbardziej znanych protokołów sieci LAN należą Ethernet i WiFi, jedynym protokołem w warstwie sieciowej jest IP (ang. <i>Internet</i> <i>Protocol</i> ), a w warstwie transportowej są dostępne dwa protokoły: TCP (dla transmisji połączeniowej) oraz UDP (dla transmisji bezpołączeniowej).
  </p>
  <br>
  <br>
  <font size=3><b><font color=#3d85c6>Warstwy 5 i 6</font></b></font><br>
  <hr size=2><a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd5 title=Sr-2-wyk-1.0-Slajd5> </a><br>
  <div id=g3lq style=TEXT-ALIGN:left>
    <img src="images/dcjpvv6n_2252cpf7mqcg_b.png" style=HEIGHT:341px;WIDTH:500px><br>
    <br>
    <p>
      Warstwa sesji to praktycznie rozwinięcie warstwy 4 o funkcje zarządzania interakcją pomiędzy komunikującymi się procesami. W tym celu definiuje szereg mechanizmów synchronizacji. Ponadto, ma ona dostarczać pewnych mechanizmów do tworzenia punktów kontrolnych, na wypadek, gdyby jedna ze stron uległa awarii podczas długo trwającej transmisji. Nie trzeba wówczas powtarzać całej transmisji, wystarczy jedynie cofnąć się do ostatniego punktu kontrolnego.<br>
    </p>
    <p>
      <br>
    </p>
    <p>
      W odróżnieniu od warstw niższych, zainteresowanych jedynie przesłaniem bitów od nadawcy do odbiorcy, warstwa prezentacji zajmuje się <i>znaczeniem</i> tych bitów. Definiuje w tym celu struktury wymienianych wiadomości oraz ich formaty, ułatwiające wymianę wiadomości pomiędzy maszynami z różnymi reprezentacjami wewnętrznymi.<br>
    </p>
    <p>
      <br>
    </p>
    <p>
      W rzeczywistości, warstwy 5 i 6 nie doczekały się realizacji w postaci odrębnych protokołów. Ich funkcje bowiem realizują protokoły aplikacyjne.
    </p>
    <br>
    <br>
    <font size=3><b><font color=#3d85c6>Warstwa aplikacji</font></b></font><br>
    <hr size=2><br>
    <div id=x.sk style=TEXT-ALIGN:left>
      <div id=wgny style=TEXT-ALIGN:left>
        <img src="images/dcjpvv6n_2254czs8wsdt_b.png" style=HEIGHT:340px;WIDTH:500px><br>
        <br>
        Warstwa aplikacji pierwotnie była przeznaczona dla standardowych aplikacji sieciowych, jak np. poczta elektroniczna, transfer plików czy emulacja terminala. Z czasem jednak znalazły w niej miejsce wszystkie te aplikacje, których z różnych powodów nie udało się umieścić w niższych warstwach. Na przykład, z perspektywy modelu OSI praktycznie wszystkie systemy rozproszone są właśnie aplikacjami.
        <p>
          <br>
        </p>
        <p>
          Należy pamiętać, że aplikacja jest czymś innym niż protokół aplikacyjny. Protokół jest bowiem <i>specyfikacją</i> , a aplikacja – <i>działającym</i> <i>programem</i> . Przykładowo, protokół <b>FTP</b> (ang. <i>File</i> <i>Transfer</i> <i>Protocol</i> ) definiuje protokół do przesyłania plików pomiędzy maszynami klienta i serwera w sieci Internet. Nie można jednak mylić protokołu z programem ftp, będącym aplikacją użytkownika wykorzystywaną do przesyłania plików i realizującą protokół FTP.
        </p>
        <br>
        <br>
        <font size=3><b><font color=#3d85c6>Warstwa pośrednia</font></b></font><br>
        <hr size=2><br>
      </div>
      <div id=vb4v style=TEXT-ALIGN:left>
        <img src="images/dcjpvv6n_2255nsq6zrf8_b.png" style=HEIGHT:341px;WIDTH:500px><br>
        <br>
        Warstwa pośrednia (ang. <i>Middleware</i> <i>layer</i> ) to szczególny rodzaj aplikacji – jej miejsce jest wprawdzie w warstwie aplikacji, ale obejmuje ona szereg protokołów ogólnego przeznaczenia, które powinny znaleźć się w odrębnej warstwie w postaci zbioru usług dla warstwy wyższej. Istnieje wiele protokołów warstwy pośredniej, jak np. uwierzytelnianie i autoryzacja, zatwierdzanie atomowe (ang. <i>Atomic</i> <i>commit</i> ), synchronizacja dostępu do zasobów czy zwielokrotnianie i związane z nim zarządzanie spójnością kopii. Wszystkie one są usługami ogólnego przeznaczenia, czyli niezależnymi od konkretnej aplikacji. Z tego względu wyodrębnia się je w postaci osobnej warstwy, jak to ukazuje następny slajd.<br>
        <br>
        <br>
        <font size=3><b><font color=#3d85c6>Model z warstwą pośrednią</font></b></font><br>
        <hr size=2><br>
        <div id=x-3o style=TEXT-ALIGN:left>
          <img src="images/dcjpvv6n_2256c9kfrsgq_b.png" style=HEIGHT:340px;WIDTH:500px>
        </div>
        <br>
        W porównaniu z modelem OSI, warstwy sesji i prezentacji zostały tu zastąpione warstwą pośrednią, zawierającą protokoły niezależne od aplikacji. Funkcjonalność warstw sesji i prezentacji jest natomiast realizowana przez warstwy pośrednią i aplikacji.<br>
        <br>
        <p>
          W dalszej części wykładu zostaną omówione cztery wysokopoziomowe usługi warstwy pośredniej: zdalne wywoływanie procedur, zdalne wywoływanie metod, systemy transferu wiadomości oraz komunikacja strumieniowa. Wszystkie te usługi na niższym poziomie wykorzystują oczywiście przesyłanie wiadomości.
        </p>
        <br>
        <br>
        <font size=3><b><font color=#3d85c6>RPC - koncepcja</font></b></font><br>
        <hr size=2><br>
        <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd9 title=Sr-2-wyk-1.0-Slajd9> </a>
        <div id=v4ij style=TEXT-ALIGN:left>
          <img src="images/dcjpvv6n_22575m4p8fc6_b.png" style=HEIGHT:340px;WIDTH:500px><br>
          <br>
          Wymiana wiadomości stanowi podstawę komunikacji pomiędzy procesami w systemie rozproszonym. Okazuje się jednak niewystarczająca do modelowania komunikacji z dwóch podstawowych powodów. Nie zapewnia bowiem przezroczystości rozproszenia. Przykładowo, jawne wysłanie wiadomości do innego procesu oznacza, że proces nadawcy musi być świadomy, do kogo wysyła wiadomość, a to oznacza, że jest świadomy rozproszenia. Ponadto, w sytuacji gdy wiadomość przesyłana jest pomiędzy maszynami o różnych wewnętrznych reprezentacjach danych, proces nadawcy musi wysyłaną wiadomość dostosować do reprezentacji odbiorcy, co znacznie utrudnia osiągnięcie przezroczystości dostępu (ang. <i>Access</i> <i>transparency</i>).<br>
          <br>
          <p>
            W 1984 roku zaproponowano nowy sposób komunikacji pomiędzy procesami na różnych maszynach, polegający na wywoływaniu procedur znajdujących się na innej maszynie. Informacje dodatkowe oraz wyniki mogą być przekazane w postaci parametrów. W ten sposób udaje się zupełnie ukryć przed programistą przekazywanie wiadomości. Model ten nazwano <b>zdalnym</b> <b>wywoływaniem</b> <b>procedur</b> , w skrócie <b>RPC</b> (ang. <i>Remote</i> <i>Procedure</i> <i>Call</i>).<br>
          </p>
          <p>
            <br>
          </p>
          <p>
            Chociaż podstawowa idea wydaje się być prosta, pozostaje kilka poważnych problemów do rozwiązania. Przede wszystkim, wywołująca i wywoływana procedura znajdują się w różnych maszynach i są wykonywane w różnych przestrzeniach adresowych, a to powoduje pewne komplikacje. Należy ponadto przekazać parametry, co również może rodzić komplikacje, szczególnie w przypadku, gdy maszyny nie są identyczne. Wreszcie, każda ze stron może ulec awarii, co rodzi kolejne problemy. Większość wspomnianych tu komplikacji udaje się jednak rozwiązać, a RPC ciągle jest popularną techniką, stanowiącą podstawę wielu systemów rozproszonych.
          </p>
          <br>
          <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd10 title=Sr-2-wyk-1.0-Slajd10> </a><br>
          <font size=3><b><font color=#3d85c6>Interakcja klienta i serwera</font></b></font><br>
          <hr size=2><br>
        </div>
        <div id=oyja style=TEXT-ALIGN:left>
          <img src="images/dcjpvv6n_2258f9sts3dh_b.png" style=HEIGHT:341px;WIDTH:500px><br>
          <br>
          Gdy proces na maszynie klienta wywołuje zdalną procedurę, znajdującą się w maszynie serwera, zostaje zawieszony w oczekiwaniu na wynik wywołania. Wywołanie procedury zostaje przetworzone na komunikat sieciowy, który trafia do maszyny serwera. Serwer, po otrzymaniu wiadomości, odtwarza z niej wywoływaną procedurę wraz z wartościami parametrów, i po jej wykonaniu zwraca wynik, który jest następnie przesłany w postaci wiadomości do maszyny klienta.<br>
          <br>
          <br>
          <font size=3><b><font color=#3d85c6>Pieniek klienta i serwera</font></b></font><br>
          <hr size=2><br>
          <div id=atuo style=TEXT-ALIGN:left>
            <img src="images/dcjpvv6n_2259dprsgng7_b.png" style=HEIGHT:340px;WIDTH:500px><br>
            <br>
            Podstawowy problem jest następujący: <i>Jak</i> <i>można</i> <i>sprawić</i> <i>,</i> <i>by</i> <i>z</i> <i>punktu</i> <i>widzenia</i> <i>uczestniczących</i> <i>procesów</i> <i>wywołanie</i> <i>zdalne</i> <i>przypominało</i> <i>lokalne</i> <i>?</i> Innymi słowy, celem jest dostarczenie procesowi wywołującemu wrażenia, że wywołuje zwyczajną, lokalną procedurę, a procesowi obsługującemu – że wywołanie pochodzi z lokalnej maszyny. Najistotniejsze jest ukrycie rozproszenia oraz komunikacji sieciowej.<br>
            <br>
            <p>
              Rozwiązaniem jest tak zwany <b>pieniek</b> (ang. <i>stub</i> ). <b>Pieniek</b> <b>klienta</b> to procedura, którą w rzeczywistości wywołuje klient, a która przetwarza wywołanie i wartości jego parametrów na komunikat sieciowy. Z punktu widzenia procesu klienta wywołanie zdalne przebiega wówczas tak samo, jak lokalne. Komunikat sieciowy, po dotarciu do maszyny serwera, musi zostać na powrót przetworzony do postaci wywołania procedury. Zajmuje się tym <b>pieniek</b> <b>serwera</b> . Po odtworzeniu z wiadomości wywołania pieniek serwera dba o jego wykonanie, a następnie wynik, wraz z parametrami przekształca na wiadomość sieciową i wysyła do procesu klienta. Z punktu widzenia zdalnej procedury wydaje się więc, że wywołanie pochodzi z lokalnej maszyny. Wszelką „świadomość rozproszenia” posiadają pieńki po obydwu stronach, a nie same procesy klienta i serwera.<br>
            </p>
            <p>
              <br>
            </p>
            <p>
              Zastosowanie pieńków nie byłoby atrakcyjne dla programisty, gdyby sam musiał je tworzyć. Okazuje się jednak, że pieńki mogą być w całości wygenerowane automatycznie. Zostanie to omówione na jednym z kolejnych slajdów.
            </p>
            <br>
            <br>
            <font size=3><b><font color=#3d85c6>Problem przekazania parametrów</font></b></font><br>
            <hr size=2><br>
          </div>
          <div id=q2n6 style=TEXT-ALIGN:left>
            <img src="images/dcjpvv6n_2260t3hnkt97_b.png" style=HEIGHT:340px;WIDTH:500px>
          </div>
          <br>
          Na rysunku ukazano stos procesu, który wywołuje lokalną procedurę. Za przykład weźmy wywołanie add w języku C, obliczające sumę dwóch liczb całkowitych, i oraz j. Jeśli wywołanie nastąpi w programie głównym, na krótko przed wywołaniem stos wygląda tak, jak ukazuje lewa część rysunku. Aby wykonać funkcję, program odkłada wartości parametrów na stosie, począwszy od skrajnie prawego (takie rozwiązanie przyjęto dla języka C). Po wykonaniu add, wynik zostaje zapisany w rejestrze, adres powrotu jest usuwany ze stosu, a sterowanie powraca do programu głównego. Następnie program główny usuwa parametry ze stosu, przywracając go do postaci, którą miał przed wywołaniem.<br>
          <br>
          <p>
            Dla przykładu, w języku C parametry przekazywane są przez wartość (<i>call-by-value</i> ) lub przez wskaźnik/odniesienie (<i>call-by-reference</i> ). Przekazanie przez wartość polega na utworzeniu kopii wartości parametru na stosie, a przekazanie przez wskaźnik odbywa się przez zapisanie na stosie <i>adresu</i> <i>w</i> <i>pamięci</i> , przeznaczonego na przechowanie wartości parametru. W języku C wartości typów prostych przekazywane są zawsze przez wartość, a wartości typów tablicowych – przez wskaźnik.<br>
          </p>
          <p>
            <br>
          </p>
          <p>
            Powstaje problem, jak przekazywać parametry zdalnej procedurze. Przekazanie parametrów typów prostych odbywa się przez kopię. Pieniek klienta umieszcza wartość parametru w komunikacie sieciowym, wysyłanym do zdalnej procedury, a pieniek serwera ją później odtwarza. Wszystko to musi się po obydwu stronach odbywać zgodnie z ustalonym wcześniej protokołem przetwarzania wywołania do- i z wiadomości sieciowej.<br>
          </p>
          <p>
            <br>
          </p>
          <p>
            Przekazywanie parametrów typów tablicowych o znanych rozmiarach w zasadzie odbywa się podobnie, z tym, przekazanie kopii następuje tutaj dwukrotnie. W pierwszej kolejności kopia wartości elementów tablicy jest przesyłana do pieńka serwera. Później, po wykonaniu procedury, pieniek serwera odsyła klientowi kopię tablicy, zawierającej ewentualne zmiany wprowadzone przez procedurę. Jest to technika znana pod angielską nazwą <i>copy-restore</i> . Dla parametrów o charakterze wyłącznie wejściowym lub wyłącznie wyjściowym można ją optymalizować, rezygnując z przesłania kopii w jedną stronę.<br>
          </p>
          <p>
            <br>
          </p>
          <p>
            Dużo bardziej skomplikowane jest przekazywanie wartości złożonych typów danych, których rozmiar nie jest znany. Niektóre systemy próbują rozwiązać ten problem, wymagając od programisty dostarczenia dodatkowych procedur do przekazania takich parametrów.<br>
          </p>
          <p>
            <br>
          </p>
          <p>
            Drugi problem bierze się z faktu, że w różnych architekturach maszyn stosuje się różne reprezentacje elementarnych typów danych. Rozwiązanie polega najczęściej na wprowadzeniu <i>zewnętrznej</i> <i>,</i> <i>uniwersalnej</i> reprezentacji, do której muszą się dostosować obie komunikujące się strony.
          </p>
          <br>
          <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd13 title=Sr-2-wyk-1.0-Slajd13> </a><br>
          <font size=3><b><font color=#3d85c6>RPC krok po kroku</font></b></font><br>
          <hr size=2><br>
        </div>
        <div id=rw2. style=TEXT-ALIGN:left>
          <img src="images/dcjpvv6n_2261dsq4vhdr_b.png" style=HEIGHT:342px;WIDTH:500px><br>
          <br>
          Na rysunku ukazano kolejne kroki wykonywania zdalnej procedury add, zachodzące od momentu wywołania przez klienta jego pieńka do momentu faktycznego wykonania procedury po stronie serwera. Poniżej wypunktowano te kroki, z uzupełnieniem ich o etap przesyłania wyniku do klienta.<br>
          <br>
          <ol>
            <li>
              Klient wywołuje procedurę add, która w rzeczywistości jest jego pieńkiem.
            </li>
            <li>
              Pieniek klienta przetwarza wywołanie na wiadomość sieciową (ID procedury: „add”, parametr 1: typ int, wartość=i, parametr 2: typ int, wartość = j).
            </li>
            <li>
              System operacyjny klienta wysyła wiadomość sieciową.
            </li>
            <li>
              Wiadomość jest przesyłana przez sieć komputerową do maszyny serwera.
            </li>
            <li>
              System operacyjny serwera przekazuje wiadomość pieńkowi serwera.
            </li>
            <li>
              Pieniek odtwarza wywołanie z wiadomości sieciowej.
            </li>
            <li>
              Pieniek wywołuje lokalnie procedurę add i zapamiętuje wynik.
            </li>
            <li>
              Pieniek serwera przetwarza wynik wywołania na wiadomość sieciową i przekazuje swojemu systemowi operacyjnemu w celu wysłania przez sieć.
            </li>
            <li>
              System operacyjny serwera wysyła wiadomość do systemu operacyjnego klienta.
            </li>
            <li>
              System operacyjny klienta przekazuje wiadomość pieńkowi klienta.
            </li>
            <li>
              Pieniek klienta przetwarza wiadomość sieciową na wynik wywołania i zwraca ten wynik procesowi klienta.
            </li>
          </ol>
          <br>
          <br>
          <font size=3><b><font color=#3d85c6>Generacja pieńków</font></b></font><br>
          <hr size=2><br>
          <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd14 title=Sr-2-wyk-1.0-Slajd14> </a>
          <div id=p2ep style=TEXT-ALIGN:left>
            <img src="images/dcjpvv6n_2262g2mdbjfj_b.png" style=HEIGHT:341px;WIDTH:500px><br>
            <br>
            Ponieważ funkcje pieńka klienta i serwera zależą wyłącznie od interfejsu procedury, kod programu realizujący pieńka można automatycznie wygenerować na podstawie definicji tego interfejsu. W praktyce wszystkie implementacje RPC dostarczają własnej odmiany języka do definiowania interfejsu. Jednym z takich języków jest IDL, od angielskiej nazwy <i>Interface</i> <i>Definition</i> <i>Language</i> . Definicja interfejsu w języku IDL jest kompilowana na kod pieńków klienta i serwera. Pozwala to zwolnić programistę z obowiązku samodzielnego tworzenia pieńka i tym samym znacząco uprościć i przyspieszyć konstrukcję systemu rozproszonego.<br>
            <br>
            <br>
            <font size=3><b><font color=#3d85c6>RMI - koncepcja</font></b></font><br>
            <hr size=2><br>
            <div id=wyev style=TEXT-ALIGN:left>
              <img src="images/dcjpvv6n_2263fgmsbshm_b.png" style=HEIGHT:343px;WIDTH:500px><br>
              <br>
              Technologia obiektowa okazała się bardzo atrakcyjnym narzędziem budowy aplikacji. Jedną z najistotniejszych właściwości obiektu jest to, że jego stan jest ukryty przed światem zewnętrznym, natomiast dostęp do niego odbywa się tylko przez jego operacje, które udostępnia na zewnątrz. Operacje te tworzą interfejs obiektu. Takie podejście pozwala zmieniać w razie potrzeby implementację obiektu, pod warunkiem że interfejs obiektu pozostaje bez zmian.
              <p>
                <br>
              </p>
              <p>
                Z czasem, gdy RPC stało się najpopularniejszą techniką komunikacji procesów w systemach rozproszonych, pojawił się pomysł, by połączyć je z przetwarzaniem obiektowym, pozwoli to bowiem podnieść poziom przezroczystości rozproszenia względem tradycyjnego RPC. Ten nowy model obiektowego RPC nazwano <b>zdalnym</b> <b>wywoływaniem</b> <b>metod</b> , w skrócie <b>RMI</b> , od angielskiej nazwy <i>Remote</i> <i>Method</i> <i>Invocation</i>.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                W dalszej części wykładu skupimy się na stosunkowo prostym modelu RMI, w którym cały stan obiektu znajduje się w jednym miejscu, a więc nie jest rozproszony.
              </p>
              <br>
              <br>
              <font size=3><b><font color=#3d85c6>Organizacja zdalnego obiektu</font></b></font><br>
              <hr size=2><br>
            </div>
            <div id=ez8v style=TEXT-ALIGN:left>
              <img src="images/dcjpvv6n_2264h3xdt6g6_b.png" style=HEIGHT:342px;WIDTH:500px><br>
              <br>
              Kluczową cechą obiektu jest jego budowa. Obiekt tworzą dane, nazywane <b>stanem</b> , oraz operacje, które manipulują tymi danymi, nazywane <b>metodami</b> . Dostęp do danych obiektu odbywa się wyłącznie za pośrednictwem metod. Zbiór metod obiektu udostępnionych na zewnątrz to tak zwany <b>interfejs</b> obiektu. Jeden obiekt może implementować kilka interfejsów, i na odwrót – jeden interfejs może być implementowany przez wiele obiektów. Podobnie jak w RPC, interfejs obiektu jest zazwyczaj definiowany w specjalnym języku deklaratywnym, IDL. Proces na maszynie serwera, który przechowuje dany obiekt, będziemy nazywać serwerem; pojęcia serwera i obiektu będziemy często używać zamiennie.<br>
              <br>
              <p>
                Rozgraniczenie pomiędzy interfejsami a obiektami je implementującymi ma w systemach rozproszonych kluczowe znaczenie. Możliwe jest bowiem umieszczenie interfejsu i obiektu <i>na</i> <i>różnych</i> <i>maszynach</i> . Taka organizacja jest powszechnie nazywana <b>rozproszonym</b> <b>obiektem</b> lub <b>zdalnym</b> <b>obiektem</b> . Należy zaznaczyć, że wbrew nazwie stan obiektu rozproszonego nie musi być rozproszony.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Kiedy klient <b>dowiązuje</b> <b>się</b> (ang. <i>bind</i> ) do obiektu, implementacja interfejsu obiektu po stronie klienta, nazywana <b>pośrednikiem</b> (ang. <i>proxy</i> ), jest ładowana do przestrzeni adresowej klienta. Pośrednik jest tym samym, co pieniek klienta w modelu RPC. Jedynym jego zadaniem jest przetwarzanie wywołań metod zdalnego obiektu do postaci komunikatu sieciowego oraz odtwarzanie wyników tych wywołań z odbieranych od serwera komunikatów.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Rzeczywisty obiekt znajduje się na maszynie serwera. Obiekt ten udostępnia taki sam interfejs, jak pośrednik klienta. Rolę pieńka serwera pełni tak zwany <b>szkielet</b> (ang. <i>skeleton</i> ), który przetwarza odbierane z sieci wiadomości na wywołania metod oraz wyniki tych wywołań na wiadomości sieciowe, odsyłane klientowi.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Kod pośrednika oraz szkieletu jest, podobnie jak w przypadku RPC, jest automatycznie generowany na podstawie definicji interfejsu obiektu.
              </p>
              <br>
              <br>
              <font size=3><b><font color=#3d85c6>Odniesienie do obiektu</font></b></font><br>
              <hr size=2><a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd17 title=Sr-2-wyk-1.0-Slajd17> </a><br>
            </div>
            <div id=jyvt style=TEXT-ALIGN:left>
              <img src="images/dcjpvv6n_22655nfbprc9_b.png" style=HEIGHT:342px;WIDTH:500px><br>
              <p>
                <br>
                Zasadnicza różnica pomiędzy tradycyjnym modelem RPC a modelem RMI tkwi w tym, że RMI wprowadza pojęcie globalnego w skali systemu adresu obiektu, nazywanego <b>odniesieniem</b> <b>obiektowym</b> (ang. <i>object</i> <i>reference</i> ). Takie odniesienie może być swobodnie przesyłane pomiędzy procesami pracującymi na różnych maszynach, na przykład w postaci parametru wywołania.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Ponadto, odniesienie najczęściej jest implementowane tak, by jego wnętrze było nieczytelne, tzn. by proces nie mógł odczytać z niego, gdzie znajduje się obiekt. Pozwala to zwiększyć stopień przezroczystości rozproszenia zasobów systemu.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Jednym z najważniejszych problemów projektowych jest ustalenie, jakie informacje adresowe zostaną zapisane w odniesieniu. Przykładowo, jeśli w odniesieniu znajdzie się adres IP serwera oraz numer portu, na którym obiekt (serwer) oczekuje na zgłoszenia, takie odniesienie będzie bardzo wrażliwe na ewentualną awarię serwera. Gdyby do niej doszło, zdalny obiekt może po wznowieniu pracy używać innego numeru portu, a to by oznaczało, że wszystkie dotychczasowe odniesienia do niego stają się nieważne.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Przykładowe rozwiązanie tego problemu polega na uruchomieniu na maszynie serwera wyróżnionego procesu, będącego rejestrem obiektów, oczekującego na wywołania na dobrze znanym numerze portu, zarezerwowanym tylko dla siebie. Rejestr przyjmowałby wywołania do obiektów, identyfikował wywoływany obiekt i przekazywał mu wywołanie. W odniesieniu znalazłby się wówczas tylko adres procesu-rejestru oraz identyfikator wywoływanego obiektu. Takie podejście (zastosowane zresztą w systemie DCE) pozwala częściowo uniezależnić odniesienie od dokładnego adresu obiektu, konkretnie od numeru portu. Nie umożliwia jednak przenoszenia procesu serwera wraz z jego obiektami na inną maszynę.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Oczywistym rozwiązaniem wydaje się być zastosowanie <b>serwera</b> <b>lokalizacji</b> , pamiętającego adres maszyny, na której aktualnie działa poszukiwany obiekt. Odniesienie zawierałoby wówczas wyłącznie adres serwera lokalizacji oraz identyfikator pozwalający odnaleźć szukany obiekt. Jednak i to podejście ma poważne ograniczenia, związane głównie z kwestią przeciążenia serwera lokalizacji, a tym samym z kwestią skalowalności systemu.
              </p>
              <br>
              <br>
              <font size=3><b><font color=#3d85c6>Rodzaje obiektów</font></b></font><br>
              <hr size=2><br>
            </div>
            <div id=nlcb style=TEXT-ALIGN:left>
              <img src="images/dcjpvv6n_2266d4t97scd_b.png" style=HEIGHT:340px;WIDTH:500px><br>
              <br>
              Należy podkreślić, że pojęcie <i>obiektu</i> w modelu RMI dotyczy głównie <i>wrażenia</i> , jakie system dostarcza aplikacji klienta. Najważniejsze jest to, by klientowi wydawało się, że pracuje z obiektem. Kwestia rzeczywistej realizacji tej abstrakcji obiektu jest drugorzędna. Chociaż najprostszym podejściem wydaje się być takie, w którym zdalne obiekty są realizowane przez obiekty języka programowania, w ogólności tak być nie musi. Obiekt zdalny może zostać zaimplementowany w dowolny sposób, pod warunkiem, że klient będzie miał złudzenie pracy z obiektem. W przypadku zdalnych obiektów realizowanych w nieobiektowych językach programowania, za dostarczanie klientowi tego złudzenia odpowiada <b>adapter</b> <b>obiektu</b> (ang. <i>Object</i> <i>adapter</i> ). Jego rolą jest dostosowanie rzeczywistej implementacji obiektu do postaci, której oczekuje klient.
              <p>
                <br>
              </p>
              <p>
                Obiekty są również klasyfikowane ze względu na ich trwałość. <b>Obiekty</b> <b>trwałe</b> (ang. <i>persistent</i> ) charakteryzują się tym, że istnieją nawet wtedy, gdy nie znajdują się aktualnie w przestrzeni adresowej procesu serwera. Innymi słowy, są niezależne od bieżącego serwera i mogą przetrwać jego awarię. W praktyce oznacza to, że stan takich obiektów musi zostać przechowany w pamięci trwałej. W przeciwieństwie do nich, <b>obiekty</b> <b>ulotne</b> (ang. <i>transient</i> ) istnieją tylko tak długo, jak długo działa utrzymujący je serwer.
              </p>
              <br>
              <br>
              <font size=3><b><font color=#3d85c6>Wywołanie statyczne i dynamiczne</font></b></font><br>
              <hr size=2><br>
            </div>
            <div id=x.f2 style=TEXT-ALIGN:left>
              <img src="images/dcjpvv6n_2267hhfm9dfj_b.png" style=HEIGHT:340px;WIDTH:500px><br>
              <br>
              Wywołania statyczne dokonywane są przez klienta za pomocą statycznego pośrednika (pieńka). Wywołania dynamiczne zaś nie wykorzystują statycznego pośrednika. Polegają natomiast na użyciu po stronie klienta ogólnej funkcji, umożliwiającej dynamiczne utworzenie wywołania. Innymi słowy, korzystając z wywołań dynamicznych, klient w dużej mierze sam robi to, co zrobiłby za niego jego pośrednik.<br>
              <br>
              <p>
                Na slajdzie ukazano ogólną funkcję invoke, umożliwiającą dynamiczne utworzenie dowolnego wywołania zdalnej metody. W ramach jej parametrów należy określić szukany obiekt, wywoływaną w nim metodę, oraz wartości parametrów wejściowych i ewentualnie wyjściowych.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Przykładowo, dla wywołania statycznego postaci:<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                MójObiekt.MojaMetoda(i)<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                odpowiadające mu wywołanie dynamiczne wyglądałoby następująco:<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Invoke(MójObiekt, ID(MojaMetoda), i, NULL).<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                W wielu sytuacjach wykorzystanie wywołań dynamicznych okazuje się koniecznością. Dzieje się tak na przykład w systemach, które przekierowują wywołania, powielają je do większej liczby odbiorców czy też w przeglądarkach obiektów.
              </p>
              <br>
              <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd20 title=Sr-2-wyk-1.0-Slajd20> </a><br>
              <font size=3><b><font color=#3d85c6>Przekazywanie parametrów</font></b></font><br>
              <hr size=2><br>
            </div>
            <div id=nna9 style=TEXT-ALIGN:left>
              <img src="images/dcjpvv6n_2268dbvcrnfn_b.png" style=HEIGHT:341px;WIDTH:500px><br>
              <br>
              <p>
                Dopóki przekazywanym parametrem nie będzie obiekt, stosuje się rozwiązania podobne do tych, które przedstawiono przy okazji tradycyjnego RPC. W modelu RMI pojawia się jednak nowy typ parametru, mianowicie obiekt.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Obiekty przekazywane są na dwa sposoby. Dla obiektów zdalnych, czyli takich, które powinny znajdować się tylko w jednej lokalizacji i być dostępne zdalnie, jedyną możliwością jest przekazanie <i>przez</i> <i>odniesienie</i> . Przekazywana jest kopia odniesienia do zdalnego obiektu. Proces otrzymujący kopię odniesienia posiada więc wskazanie na ten sam zdalny obiekt. Na przedstawionym rysunku widać, jak proces działający w maszynie A wywołuje zdalną metodę procesu maszyny C i przekazuje jako parametr odniesienie R1 do zdalnego obiektu O2. Od tej chwili na obiekt O2 wskazują dwa identyczne odniesienia. Wszelkie wywołania metod obiektu O2 mają zawsze charakter zdalny.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Dla obiektów lokalnych, a więc takich, które nie są dostępne zdalnie, jedyną opcją jest przekazanie ich <i>przez</i> <i>wartość</i> (in. przez kopię). Stan takich obiektów jest w całości kopiowany i przesyłany jako parametr metody. Na rysunku widać, jak lokalny obiekt O1 zostaje przekazany jako parametr wywołania zdalnego, dokonywanego przez proces maszyny A na obiekcie w maszynie C – w serwerze maszyny C tworzona jest kopia obiektu O1, a późniejsze wywołania metod obiektu O1 mają charakter lokalny.
              </p>
              <br>
              <br>
              <font size=3><b><font color=#3d85c6>System transferu wiadomości - organizacja</font></b></font><br>
              <hr size=2><br>
            </div>
            <div id=mq7y style=TEXT-ALIGN:left>
              <img src="images/dcjpvv6n_2269cr62ddf9_b.png" style=HEIGHT:342px;WIDTH:500px><br>
              <br>
              Istnieje szereg zastosowań, dla których modele RPC i RMI okazują się niewystarczające. Dotyczy to szczególnie aplikacji, w których nie można zakładać, że odbiorca wiadomości jest aktywny podczas jej przesyłania. Ponadto, synchroniczny charakter wywołań procedur czy metod, przy których klient jest blokowany do momentu otrzymania wyniku, często stanowi zbyt wielkie ograniczenie.<br>
              <br>
              <p>
                Odpowiedzią na te ograniczenia są <b>systemy</b> <b>transferu</b> <b>wiadomości</b> . Niniejsza część wykładu prezentuje komunikację zorientowaną na wiadomości. Omawia dostępne rodzaje komunikacji oraz ich przykładowe realizacje.<br>
              </p>
              <p>
                <br>
              </p>
              <p>
                Na rysunku przedstawiono ogólną organizację systemu, w którym przesyłane są wiadomości. Aplikacje są zawsze wykonywane na komputerach końcowych, udostępniających interfejs, przez który wiadomości mogą być wysyłane. Komputery końcowe są połączone ze sobą za pośrednictwem sieci serwerów komunikacyjnych, odpowiedzialnych za przekazywanie (i routowanie) wiadomości. Zarówno komputery końcowe, jak i serwery komunikacyjne posiadają bufory, w których zapamiętują przesyłane wiadomości.
              </p>
              <br>
              <br>
              <font size=3><b><font color=#3d85c6>Rodzaje komunikacji</font></b></font><br>
              <hr size=2><br>
              <div id=kh.4 style=TEXT-ALIGN:left>
                <img src="images/dcjpvv6n_2270ddq3q5dm_b.png" style=HEIGHT:341px;WIDTH:500px><br>
                <br>
                <p>
                  Z punktu widzenia trwałości wiadomości wyróżniamy dwa rodzaje komunikacji. Komunikacja jest <b>trwała</b> (ang. <i>persistent</i> ), jeśli wysłana wiadomość jest pamiętana w systemie komunikacyjnym do momentu jej dostarczenia do odbiorcy. Odnosząc się do rysunku z poprzedniego slajdu można powiedzieć, że wiadomość jest pamiętana w jednym serwerze komunikacyjnym tak długo, aż zostanie dostarczona do następnego serwera komunikacyjnego. Nie ma zatem potrzeby, aby aplikacja wysyłająca kontynuowała działanie po przekazaniu wysyłanej wiadomości systemowi. Przykładem z życia codziennego usługi realizującej trwałą komunikację jest tradycyjna poczta.<br>
                </p>
                <p>
                  <br>
                </p>
                <p>
                  W komunikacji <b>nietrwałej</b> (ang. <i>transient</i> ) wiadomość jest pamiętana przez system komunikacyjny tylko tak długo, jak długo działają nadawca lub odbiorca. Odnosząc się znów do rysunku na poprzednim slajdzie, można bardziej precyzyjnie powiedzieć, że jeśli jeden serwer komunikacyjny nie będzie w stanie dostarczyć wiadomości do następnego serwera lub do odbiorcy, wiadomość zostanie porzucona. Ten sposób komunikacji przypomina działanie tradycyjnej telefonii z funkcją poczty głosowej lub automatycznej sekretarki.<br>
                </p>
                <p>
                  <br>
                </p>
                <p>
                  Druga linia podziału usług komunikacyjnych ma związek z czasem trwania operacji wysłania wiadomości. Cechą charakterystyczną komunikacji <b>asynchronicznej</b> jest to, że nadawca kontynuuje przetwarzanie natychmiast po przedłożeniu wysyłanej wiadomości w systemie. Wiadomość zostaje zapamiętana w komputerze wysyłającym lub w najbliższym serwerze komunikacyjnym. Nadawca nie jest zatem w ogóle blokowany w oczekiwaniu na jakiekolwiek potwierdzenie, przez co operacja wysłania trwa bardzo krótko. W komunikacji <b>synchronicznej</b> zaś nadawca jest blokowany do momentu, aż wiadomość znajdzie się w buforze komputera odbiorcy lub zostanie dostarczona do samego odbiorcy. Istnieje kilka odmian komunikacji synchronicznej, a w najsilniejszej z nich nadawca jest blokowany do momentu otrzymania potwierdzenia <i>przetworzenia</i> wiadomości przez odbiorcę. W dalszej części omówione zostały różne formy komunikacji, łączące różne poziomy trwałości i synchronizmu.
                </p>
                <br>
                <br>
                <font size=3><b><font color=#3d85c6>Trwała asynchroniczna</font></b></font><br>
                <hr size=2><br>
                <div id=cagl style=TEXT-ALIGN:left>
                  <img src="images/dcjpvv6n_2271fv2pgqd3_b.png" style=HEIGHT:341px;WIDTH:500px>
                </div>
                <br>
              </div>
            </div>
            W trwałej asynchronicznej komunikacji wiadomość jest trwale zapamiętana w komputerze wysyłającym lub w najbliższym serwerze komunikacyjnym. Poczta elektroniczna jest jednym z przykładów tego typu komunikacji. Na rysunku pokazano zasadę działania trwałej komunikacji asynchronicznej. Podczas samego transferu wiadomości ani nadawca, ani odbiorca nie musi pozostawać aktywny, gdyż wiadomość jest trwale zapamiętana w systemie komunikacyjnym.<br>
            <br>
          </div>
          <br>
          <font size=3><b><font color=#3d85c6>Trwała synchroniczna</font></b></font><br>
          <hr size=2><br>
        </div>
        <div id=cx3w style=TEXT-ALIGN:left>
          <img src="images/dcjpvv6n_2272dbqvpxdz_b.png" style=HEIGHT:343px;WIDTH:500px>
        </div>
        <br>
      </div>
    </div>
  </div>
  Przy komunikacji trwałej synchronicznej wiadomości mogą być trwale zapamiętane tylko w komputerze odbiorcy. Nadawca jest blokowany do momentu otrzymania potwierdzenia, że wiadomość została tam zachowana. Należy podkreślić, że aplikacja odbiorcy nie musi działać w momencie przybycia wiadomości.<br>
  <br>
  <p>
    Słabszą odmianą trwałej synchronicznej komunikacji jest usługa, w której nadawca jest blokowany do momentu, gdy wiadomość zostanie zachowana w serwerze komunikacyjnym połączonym z komputerem odbiorcy.
  </p>
  <br>
  <br>
  <font size=3><b><font color=#3d85c6>Nietrwała asynchroniczna</font></b></font><br>
  <hr size=2><br>
  <div id=xxf4 style=TEXT-ALIGN:left>
    <img src="images/dcjpvv6n_2273cw4cb7f7_b.png" style=HEIGHT:340px;WIDTH:500px><br>
    <p>
      <br>
      W komunikacji nietrwałej asynchronicznej, po przekazaniu przez nadawcę wysyłanej wiadomości systemowi komunikacyjnemu, wiadomość ta zostaje tymczasowo zapamiętana w lokalnym buforze komputera wysyłającego, a aplikacja nadawcy natychmiast kontynuuje swoją pracę. W tym samym czasie system komunikacyjny kieruje wiadomość do komputera odbiorcy, gdzie aplikacja odbiorcy powinna działać i oczekiwać na wiadomość. Jeśli odbiorca nie działa w momencie dostarczenia wiadomości, transfer się nie udaje.<br>
    </p>
    <p>
      <br>
    </p>
    <p>
      Do przykładów tego typu usługi należą: protokół UDP w warstwie transportowej oraz odmiana zdalnego wywoływania procedur, znana pod nazwą asynchronicznego RPC.
    </p>
    <br>
    <br>
    <font size=3><b><font color=#3d85c6>Nietrwała synchroniczna typu odbiór</font></b></font><br>
    <hr size=2><br>
    <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd26 title=Sr-2-wyk-1.0-Slajd26> </a>
    <div id=h7yw style=TEXT-ALIGN:left>
      <img src="images/dcjpvv6n_2274gbpbk9dd_b.png" style=HEIGHT:341px;WIDTH:500px><br>
      <br>
      Istnieje kilka odmian komunikacji nietrwałej synchronicznej. Najmniej wymagającą z nich jest odmiana typu odbiór, to znaczy taka, w której nadawca jest blokowany do momentu otrzymania potwierdzenia, że wiadomość została zapamiętana w lokalnym buforze komputera odbiorcy. Nadawca, po otrzymaniu takiego potwierdzenia, kontynuuje pracę.<br>
      <br>
      <br>
      <font size=3><b><font color=#3d85c6>Nietrwała synchroniczna typu dostarczenie</font></b></font><br>
      <hr size=2><br>
      <div id=ghmp style=TEXT-ALIGN:left>
        <img src="images/dcjpvv6n_2275d3f9xrgw_b.png" style=HEIGHT:341px;WIDTH:500px><br>
        <br>
        W bardziej wymagającej odmianie komunikacji nietrwałej synchronicznej nadawca jest blokowany do momentu otrzymania potwierdzenia, że wiadomość została dostarczona do aplikacji odbiorcy. Potwierdzenie takie może zostać wysłane jeszcze przed przetworzeniem wiadomości przez odbiorcę.<br>
        <br>
        <br>
        <font size=3><b><font color=#3d85c6>Nietrwała synchroniczna typu odpowiedź</font></b></font><br>
        <hr size=2><br>
        <div id=vq9: style=TEXT-ALIGN:left>
          <img src="images/dcjpvv6n_2276cr224wgr_b.png" style=HEIGHT:341px;WIDTH:500px><br>
          <br>
          W najbardziej wymagającej odmianie komunikacji nietrwałej synchronicznej nadawca jest blokowany do momentu, aż otrzyma potwierdzenie przetworzenia wiadomości przez aplikację odbiorcy. Do najbardziej znanych usług wykorzystujących ten typ komunikacji należą RPC oraz RMI.<br>
          <br>
          <br>
          <font size=3><b><font color=#3d85c6>Komunikacja strumieniowa - definicje</font></b></font><br>
          <hr size=2><br>
          <div id=ko13 style=TEXT-ALIGN:left>
            <img src="images/dcjpvv6n_2277cbth89fm_b.png" style=HEIGHT:340px;WIDTH:500px>
          </div>
          <br>
        </div>
      </div>
    </div>
    Dotychczas przedstawiane mechanizmy komunikacji koncentrowały się na wymianie odrębnych, kompletnych porcji informacji, na przykład wywołanie metody i późniejsza odpowiedź na wywołanie. Charakterystyczną cechą tego typu komunikacji jest to, że jej poprawność nie zależy od parametrów czasowych. Nie ma znaczenia, czy system działa za wolno lub za szybko, liczy się tylko fakt dotarcia wiadomości do celu.<br>
    <br>
    <p>
      Istnieją jednak takie formy komunikacji, w których parametry czasowe odgrywają kluczową rolę. Rozważmy na przykład strumień audio, składający się z ciągu małych próbek, przesyłanych od nadawcy do odbiorcy. Każda próbka strumienia reprezentuje amplitudę fali dźwiękowej. Aby poprawnie odtworzyć strumień u odbiorcy, nie wystarczy zachować oryginalnej kolejności próbek – należy utrzymać także taką samą częstotliwość ich występowania, jaka była u nadawcy. Odtwarzanie próbek z inną prędkością będzie skutkowało powstaniem niepoprawnej wersji oryginalnego dźwięku.<br>
    </p>
    <p>
      <br>
    </p>
    <p>
      Przez <b>medium</b> będziemy rozumieli konkretny sposób prezentowania informacji, np. dźwięk, obraz nieruchomy, obraz ruchomy, tekst itd. Istnieją dwa rodzaje mediów. W <b>mediach</b> <b>ciągłych</b> czasowe relacje pomiędzy kolejnymi jednostkami danych mają kluczowe znaczenie dla poprawności interpretacji danych. Do przykładów mediów ciągłych można zaliczyć sygnał dźwiękowy czy obraz ruchomy. W <b>mediach</b> <b>dyskretnych</b> te relacje czasowe nie mają fundamentalnego znaczenia dla poprawności transmisji. Przykładami mediów dyskretnych są: tekst, obraz nieruchomy czy kod programu. Połączenie naraz kilku form prezentacji określa się mianem komunikacji multimedialnej. W dalszej części wykładu poświęcimy uwagę wyłącznie mediom ciągłym.<br>
    </p>
    <p>
      <br>
    </p>
    <p>
      W sieciach komputerowych oraz systemach rozproszonych dane zależne od parametrów czasowych modeluje się za pomocą pojęcia <b>strumienia</b> . Strumień jest po prostu sekwencją jednostek danych.<br>
    </p>
    <p>
      <br>
    </p>
    <p>
      Dla strumienia ciągłego, to jest strumienia istniejącego w ramach ciągłego medium, wyróżnia się różne tryby transmisji. W trybie <b>asynchronicznym</b> jednostki danych tworzące strumień przesyłane są w konkretnej kolejności, ale nie istnieją żadne dodatkowe ograniczenia czasowe. W trybie <b>synchronicznym</b> dla każdej jednostki danych strumienia wyróżnia się maksymalne opóźnienie od momentu wysłania do momentu odebrania. Najbardziej wymagającym jest tryb <b>izochroniczny</b> , w którym jednostki danych należy dostarczać w ściśle ustalonym momencie; oznacza to, że istnieje w nim zarówno górna, jak i dolna granica opóźnienia.<br>
    </p>
    <p>
      <br>
    </p>
    <p>
      Strumienie dzielimy na <b>proste</b> i <b>złożone</b> . Strumień prosty jest złożony z jednej tylko sekwencji jednostek informacji, podczas gdy strumień złożony utworzony jest przez kilka powiązanych ze sobą strumieni prostych. Przykładem strumienia prostego jest monofoniczny sygnał audio, a przykładem strumienia złożonego – film, obejmujący obraz i dźwięk.
    </p>
    <br>
    <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd30 title=Sr-2-wyk-1.0-Slajd30> </a><br>
    <font size=3><b><font color=#3d85c6>Architektura systemu</font></b></font><br>
    <hr size=2><br>
    <div id=wd:z style=TEXT-ALIGN:left>
      <img src="images/dcjpvv6n_2278dcwshpgk_b.png" style=HEIGHT:342px;WIDTH:500px>
    </div>
  </div>
</div>
<p>
  <br>
  Na rysunku ukazano przykład architektury systemu, w którym wykorzystano komunikację strumieniową. Nadawaniem i odbieraniem zajmują się tu specjalizowane procesy, współpracujące z urządzeniami nadawczo-odbiorczymi. Możliwe jest również utworzenie strumienia bezpośrednio pomiędzy urządzeniami, jeśli tylko system operacyjny jest wyposażony w oprogramowanie potrafiące z nimi współpracować.
</p>
<br>
<br>
<font size=3><b><font color=#3d85c6>Jakość usług - algorytm wiadra z żetonami</font></b></font><br>
<hr size=2><br>
<div id=m.0l style=TEXT-ALIGN:left>
  <img src="images/dcjpvv6n_2279hkscxjdw_b.png" style=HEIGHT:342px;WIDTH:500px><br>
  <br>
  Od aplikacji nadawczej, generującej strumień danych, system komunikacyjny oczekuje zachowania pewnych własności strumienia. Najczęściej stosowanym modelem do opisania takich własności jest algorytm wiadra z żetonami (ang. <i>Token</i> <i>bucket</i> <i>algorithm</i> ). Celem jego zastosowania jest osiągnięcie na wyjściu aplikacji nadawczej w miarę równomiernego tempa dostarczania systemowi kolejnych jednostek danych.<br>
  <br>
  <p>
    Zasada algorytmu wiadra z żetonami została ukazana na rysunku. W równych odstępach czasu ?T do wiadra o skończonej pojemności dostarczane są żetony. Każdy żeton reprezentuje stałą liczbę <i>k</i> bajtów, które aplikacja może wysłać przez sieć. Żetony są w wiadrze buforowane, a jeśli ich ilość przekroczy dostępną pojemność wiadra, są po prostu porzucane. Za każdym razem, gdy aplikacja usiłuje przesłać do sieci jednostkę danych o rozmiarze <i>N</i> , musi usunąć co najmniej <i>N/k</i> żetonów z wiadra. Efektem zastosowania algorytmu jest uzyskanie względnie równomiernego tempa na wyjściu aplikacji, a więc – na wejściu do systemu komunikacyjnego. Algorytm pozwala jednak na przesłanie większej porcji danych naraz, jeśli w wiadrze nagromadzonych zostało wystarczająco dużo żetonów.<br>
  </p>
  <p>
    <br>
  </p>
  <p>
    Wymagania stawiane aplikacji stanowią jeden z dwóch aspektów <b>jakości</b> <b>usług</b> (ang. <i>Quality</i> <i>of</i> <i>Service</i> ), pojęcia związanego z definiowaniem i gwarantowaniem parametrów jakościowych transmisji. Drugi jego aspekt, wymagania stawiane systemowi komunikacyjnemu przez aplikację nadawczą, omówiono na kolejnym slajdzie.
  </p>
  <br>
  <br>
  <font size=3><b><font color=#3d85c6>Jakość usług - specyfikacja</font></b></font><br>
  <hr size=2><a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd32 title=Sr-2-wyk-1.0-Slajd32> </a><br>
</div>
<div id=m08f style=TEXT-ALIGN:left>
  <img src="images/dcjpvv6n_2280q3rvcvwz_b.png" style=HEIGHT:340px;WIDTH:500px><br>
  <br>
  Wymaganą przez obie strony jakość usługi najczęściej specyfikuje się w dokumencie nazywanym <b>specyfikacją</b> <b>przepływu</b> (ang. <i>flow</i> <i>specification</i> ). Jest to kontrakt pomiędzy aplikacją a systemem komunikacyjnym, zobowiązujący obie strony do zachowania określonych parametrów jakościowych transmisji. Po jednej stronie opisana jest charakterystyka wejścia, to znaczy ruch dostarczany przez aplikację na wejście systemu komunikacyjnego. Charakterystyka wejścia jest zazwyczaj zgodna z modelem algorytmu wiadra z żetonami.<br>
  <br>
  <p>
    Po drugiej zaś stronie określone są wymogi stawiane systemowi komunikacyjnemu przez aplikację. Wśród najważniejszych parametrów wyróżnia się tu:<br>
  </p>
  <p>
    <br>
  </p>
  <ul>
    <li>
      <i>Podatność</i> <i>na</i> <i>straty</i> , która w połączeniu z <i>przedziałem</i> <i>strat</i> określa maksymalne akceptowalne tempo strat (przykładowo, 1 bajt na minutę)
    </li>
    <li>
      <i>Podatność</i> <i>na</i> <i>straty</i> <i>skokowe</i> - mówi, jak wiele następujących po sobie jednostek danych może zostać utraconych
    </li>
    <li>
      <i>Minimalne</i> <i>zauważalne</i> <i>opóźnienie</i> - określa, jak długo sieć może opóźniać dostarczenie jednostki danych, zanim zauważy to odbiorca. Z tym parametrem wiąże się również <i>maksymalne</i> <i>wahanie</i> <i>opóźnienia</i> , określające maksymalne akceptowane wahanie opóźnienia
    </li>
    <li>
      Wreszcie, jakość gwarancji jest parametrem liczbowym wskazującym, jak poważnie wszystkie te wymogi powinny być traktowane. Im większa jest jego wartość, tym większe są potencjalne straty klienta na wypadek niedotrzymania przez system komunikacyjny ustalonych wartości parametrów.
    </li>
  </ul>
  <br>
  <p>
    Ponieważ użytkownikowi aplikacji na ogół trudno jest zaproponować specyfikację przepływu, w praktyce stosuje się podejście uproszczone. Polega ono na tym, że użytkownik najpierw po prostu klasyfikuje jakość swojego strumienia, a następnie zostaje mu zaproponowana specyfikacja usług z domyślnymi wartościami parametrów dla wskazanego przez niego poziomu jakości.
  </p>
  <br>
  <a href=http://wazniak.mimuw.edu.pl/index.php?title=Sr-2-wyk-1.0-Slajd33 title=Sr-2-wyk-1.0-Slajd33> </a><br>
  <font size=3><b><font color=#3d85c6>Synchronizacja strumieni</font></b></font><br>
  <hr size=2>
</div>
<br>
<div id=wnsi style=TEXT-ALIGN:left>
  <img src="images/dcjpvv6n_2281f6q8vcd9_b.png" style=HEIGHT:342px;WIDTH:500px><br>
  <br>
  Aby informacja przenoszona przez strumień złożony była czytelna, jego strumienie proste muszą być ze sobą synchronizowane. Istnieją dwa rozwiązania takiej synchronizacji. W pierwszym odpowiada za nią w całości aplikacja odbiorcza, która w określonych odstępach czasu wysyła na wyjście odpowiednie jednostki danych ze strumieni prostych. Cały mechanizm synchronizacji jest realizowany w aplikacji. Podstawową wadą tego podejścia jest jego niskopoziomowy charakter – aplikacja musi być bardzo mocno wyspecjalizowana do obsługi konkretnego strumienia, a ponadto sama odpowiada za odczytywanie i zapisywanie kolejnych jednostek informacji (np. obrazów tworzących film).<br>
  <br>
  <p>
    Lepsze podejście, ukazane na rysunku, zakłada wykorzystanie do synchronizacji warstwy pośredniej, do której przeniesione zostają niskopoziomowe mechanizmy. Aplikacja otrzymuje interfejs, pozwalający jej kontrolować strumienie oraz urządzenia. Poprzez ten interfejs aplikacja określa tylko parametry czasowe strumienia, a całą resztę funkcji – głównie odczyt kolejnych jednostek informacji oraz wysłanie ich na wyjście we właściwych momentach – realizuje warstwa pośrednia. Ponieważ warstwa pośrednia zawiera wiele interfejsów dla różnych typów strumieni oraz różnych urządzeń i oferuje je aplikacji, dana aplikacja może współpracować z wieloma różnymi typami strumieni.
  </p>
  <br>
  <br>
</div>
<br></body>
</html>